package com.nfc.lock.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.nfc.lock.common.exception.BusinessException;
import com.nfc.lock.common.result.ResultCode;
import com.nfc.lock.entity.PowerRoom;
import com.nfc.lock.entity.WarningRecord;
import com.nfc.lock.mapper.PowerRoomMapper;
import com.nfc.lock.mapper.WarningRecordMapper;
import com.nfc.lock.security.SecurityUtils;
import com.nfc.lock.service.IUserService;
import com.nfc.lock.service.IWarningRecordService;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * 预警记录服务实现类。
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class WarningRecordServiceImpl extends ServiceImpl<WarningRecordMapper, WarningRecord>
    implements IWarningRecordService {

    private final WarningRecordMapper warningRecordMapper;
    private final PowerRoomMapper powerRoomMapper;
    private final IUserService userService;

    @Override
    public IPage<WarningRecord> getWarningList(Integer pageNum, Integer pageSize,
                                               Integer warningType, Integer status,
                                               Long lockId) {
        LambdaQueryWrapper<WarningRecord> wrapper = buildQuery(warningType, status, lockId);
        List<WarningRecord> allRecords = warningRecordMapper.selectList(wrapper);
        List<WarningRecord> filtered = filterByPermission(allRecords);

        long total = filtered.size();
        Page<WarningRecord> page = new Page<>(pageNum, pageSize);
        page.setTotal(total);
        long pages = total == 0 ? 0 : (total + pageSize - 1L) / pageSize;
        page.setPages(pages);

        int fromIndex = Math.max((pageNum - 1) * pageSize, 0);
        if (fromIndex >= filtered.size()) {
            page.setRecords(Collections.emptyList());
            return page;
        }
        int toIndex = Math.min(fromIndex + pageSize, filtered.size());
        page.setRecords(filtered.subList(fromIndex, toIndex));
        return page;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void handleWarning(Long warningId, String handleRemark) {
        WarningRecord warning = warningRecordMapper.selectById(warningId);
        if (warning == null) {
            throw new BusinessException(ResultCode.NOT_FOUND);
        }
        if (warning.getStatus() != null && warning.getStatus() == 1) {
            throw new BusinessException("预警已处理，无需重复操作");
        }

        Long currentUserId = SecurityUtils.getCurrentUserId();
        if (!hasPermission(currentUserId, warning.getRoomId())) {
            throw new BusinessException(ResultCode.FORBIDDEN);
        }

        warning.setStatus(1);
        warning.setHandleUserId(currentUserId);
        warning.setHandleTime(LocalDateTime.now());
        if (handleRemark != null && !handleRemark.isEmpty()) {
            warning.setWarningContent(
                warning.getWarningContent() + "（处理说明：" + handleRemark + "）");
        }

        warningRecordMapper.updateById(warning);
        log.info("处理预警成功: {}", warningId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void createWarning(WarningRecord warningRecord) {
        if (warningRecord.getStatus() == null) {
            warningRecord.setStatus(0);
        }
        warningRecordMapper.insert(warningRecord);
        log.info("创建预警记录: {}", warningRecord.getWarningContent());
    }

    @Override
    public WarningRecord getWarningDetail(Long warningId) {
        WarningRecord warning = warningRecordMapper.selectById(warningId);
        if (warning == null) {
            throw new BusinessException(ResultCode.NOT_FOUND);
        }

        Long currentUserId = SecurityUtils.getCurrentUserId();
        if (!hasPermission(currentUserId, warning.getRoomId())) {
            throw new BusinessException(ResultCode.FORBIDDEN);
        }

        log.info("获取预警详情: {}", warningId);
        return warning;
    }

    private LambdaQueryWrapper<WarningRecord> buildQuery(Integer warningType,
                                                         Integer status,
                                                         Long lockId) {
        LambdaQueryWrapper<WarningRecord> wrapper = new LambdaQueryWrapper<>();
        if (warningType != null) {
            wrapper.eq(WarningRecord::getWarningType, warningType);
        }
        if (status != null) {
            wrapper.eq(WarningRecord::getStatus, status);
        }
        if (lockId != null) {
            wrapper.eq(WarningRecord::getLockId, lockId);
        }
        wrapper.orderByDesc(WarningRecord::getCreateTime);
        return wrapper;
    }

    private List<WarningRecord> filterByPermission(List<WarningRecord> records) {
        if (records.isEmpty()) {
            return records;
        }
        Long currentUserId = SecurityUtils.getCurrentUserId();
        Set<Long> roomIds = records.stream()
            .map(WarningRecord::getRoomId)
            .filter(Objects::nonNull)
            .collect(Collectors.toSet());
        if (roomIds.isEmpty()) {
            return Collections.emptyList();
        }

        Map<Long, PowerRoom> roomMap = powerRoomMapper.selectBatchIds(roomIds).stream()
            .filter(Objects::nonNull)
            .collect(Collectors.toMap(
                PowerRoom::getRoomId,
                room -> room,
                (existing, replacement) -> existing));

        return records.stream()
            .filter(record -> hasPermission(currentUserId, record.getRoomId(), roomMap))
            .collect(Collectors.toList());
    }

    private boolean hasPermission(Long userId, Long roomId) {
        return hasPermission(userId, roomId, null);
    }

    private boolean hasPermission(Long userId, Long roomId, Map<Long, PowerRoom> cachedRooms) {
        if (roomId == null) {
            return false;
        }
        PowerRoom room =
            cachedRooms != null ? cachedRooms.get(roomId) : powerRoomMapper.selectById(roomId);
        if (room == null) {
            return false;
        }
        return userService.checkPermission(userId, room.getRegionId());
    }
}
